package com.heima.comment.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.comment.config.ThreadPoolConfig;
import com.heima.comment.service.ApCommentService;
import com.heima.comment.service.CommentHotService;
import com.heima.common.constants.article.HotArticleConstants;
import com.heima.feigns.ApUserFegin;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentLoadDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.UpdateArticleMess;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmUser;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.signature.qual.PolySignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

/**
 * @author lo
 * @date 2021/10/3
 */
@Service
@Slf4j
public class ApCommentServiceImpl implements ApCommentService {
    @Autowired
    ApUserFegin apUserFegin;


    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    CommentHotService commentHotService;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 保存评论信息
     *
     * @param dto 文章id 评论内容
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {

        //1.获取登录用户id
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.查询用户
        ResponseResult<ApUser> userById = apUserFegin.findUserById(user.getId());
        if (userById.getCode() != 0 || userById.getData() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_STATUS_ERROR, "用户不存在");
        }
        ApUser apUser = userById.getData();
        //3.封装数据
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUser.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setContent(dto.getContent());
        apComment.setImage(apUser.getImage());
        apComment.setType((short) 0);
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        mongoTemplate.save(apComment);

        //发送消息给信息采集
        //1.封装对应点赞实体类
        UpdateArticleMess updateArticleMess = new UpdateArticleMess();
        updateArticleMess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        updateArticleMess.setArticleId(dto.getArticleId());
        updateArticleMess.setAdd(1);
        //2.发送消息
        rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE, JSON.toJSONString(updateArticleMess));



        return ResponseResult.okResult();
    }

    /**
     * 分页加载文章列表
     *
     * @param dto 文章id
     * @return
     */
    @Override
    public ResponseResult loadComment(CommentLoadDTO dto) {
        //1.校验参数
        if (dto.getSize() == null) {
            dto.setSize(10);
        }

        //每页多少条
        Integer size = dto.getSize();

        //TODO 查询热点评论
        // 文章评论的首页
        List<ApComment> apComments = null;
        if (dto.getIndex().intValue() == 1) {
            //查询热点评论  5
            apComments = mongoTemplate.find(Query.query(Criteria.
                    where("articleId").is(dto.getArticleId()).
                    and("flag").is((short) 1))
                    .with(Sort.by(Sort.Direction.DESC, "likes")), ApComment.class);

            if(CollectionUtils.isNotEmpty(apComments)){
                size -= apComments.size();
                List<ApComment> normalComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
                apComments.addAll(normalComments);
            }else {
                apComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
            }
        }else {
            apComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
        }
        //3.用户未登录返回评论列表
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.okResult(apComments);
        }
        Integer userId = user.getId();
        //4.如果用户登录,返回用户点赞过得评论列表
        List<ApCommentVo> apCommentVoList = new ArrayList<>();

        List<String> collect = apComments.stream().map(apComment -> apComment.getId()).collect(Collectors.toList());

        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where("authorId").is(userId).and("commentId").in(collect)), ApCommentLike.class);
        //5.封装数据
        if (CollectionUtils.isNotEmpty(apCommentLikes) && CollectionUtils.isNotEmpty(apComments)){
            //遍历评论列表
            apComments.forEach(comment->{
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(comment,apCommentVo);
                //遍历点赞列表
                apCommentLikes.forEach(apCommentLike->{
                    if (comment.getId().equals(apCommentLike.getCommentId())){
                        apCommentVo.setOperation((short)0);
                    }
                });
                apCommentVoList.add(apCommentVo);
            });
            return ResponseResult.okResult(apCommentVoList);
        }
        return ResponseResult.okResult(apComments);
    }

    /**
     * 构建查询条件
     */
    public Query getQuery(CommentLoadDTO dto,Integer size){
        Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("flag").is(0)
                .and("createdTime").lt(dto.getMinDate()))
                .limit(size)
                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
       return query;
    }

    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        //1.获取用户id
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer loginId = user.getId();

        // todo 加锁
        RLock likeLock = redissonClient.getLock("likes-lock");
        likeLock.lock();
        ApComment comment;

        try {
            //2.查询评论
            comment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (comment == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
            }

            //判断是否是点赞
            if (dto.getOperation() == 0) {
                //1.判断是否已经点赞过
                ApCommentLike commentLike = mongoTemplate.findOne(Query.query(Criteria.where("commentId").is(dto.getCommentId()).and("authorId").is(loginId)), ApCommentLike.class);
                if (commentLike != null) {
                    //不能重复点赞
                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW, "不能重复点赞");
                }
                //评论点赞数加1
                comment.setLikes(comment.getLikes() + 1);
                mongoTemplate.save(comment);

                //TODO 异步计算热点评论评论
                if (comment.getLikes() >= 10 && comment.getFlag().shortValue() == 0) {
                    commentHotService.hotCommentExecutor(comment);
                }

                //2.点赞--添加点赞数据
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(loginId);
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);
            } else if (dto.getOperation() == 1) {

                comment.setLikes(comment.getLikes() > 0 ? comment.getLikes() - 1 : 0);
                mongoTemplate.save(comment);

                //3.取消点赞--删除点赞数据
                mongoTemplate.remove(Query.query(Criteria
                        .where("commentId").is(dto.getCommentId())
                        .and("authorId").is(loginId)), ApCommentLike.class);

            }
        } finally {
            likeLock.unlock();
        }
        //返回数据
        HashMap<String, Object> map = new HashMap<>(8);
        map.put("likes",comment.getLikes());

        return ResponseResult.okResult(map);
    }
}
